#include "Log.h"
#include <spdlog/sinks/stdout_sinks.h>
#include "spdlog/sinks/rotating_file_sink.h"

namespace Log
{
    std::shared_ptr<spdlog::logger> ConsoleLog = nullptr;
    std::shared_ptr<spdlog::logger> GameLog = nullptr;
    std::shared_ptr<spdlog::logger> PlayerLog = nullptr;
    std::shared_ptr<spdlog::logger> TerrainLog = nullptr;
    std::shared_ptr<spdlog::logger> NetLog = nullptr;

    void Init()
    {

        // 创建一个多线程控制台日志器
        ConsoleLog = spdlog::stdout_logger_mt("console_logger");
        ConsoleLog->set_pattern("[%H:%M:%S.%e][%n][%l] %v");
        // ConsoleLog->set_pattern("[\033[1;36m%H:%M:%S.%e\033[0m][%n][%l] %v");

        // ConsoleLog = spdlog::default_logger();
        // ConsoleLog->set_pattern("[%H:%M:%S.%e][%n][%l] %v");

        GameLog = spdlog::rotating_logger_mt("Game", "Logs/Game.log", 1048576 * 5, 3);
        GameLog->set_pattern("[%Y-%m-%d %H:%M:%S.%e][%l] %v");
        GameLog->sinks().push_back(ConsoleLog->sinks().front());

        PlayerLog = spdlog::rotating_logger_mt("Player", "Logs/Player.log", 1048576 * 5, 3);
        PlayerLog->set_pattern("[%Y-%m-%d %H:%M:%S.%e][%l] %v");
        PlayerLog->sinks().push_back(ConsoleLog->sinks().front());

        TerrainLog = spdlog::rotating_logger_mt("Terrain", "Logs/Terrain.log", 1048576 * 5, 3);
        TerrainLog->set_pattern("[%Y-%m-%d %H:%M:%S.%e][%l] %v");

        NetLog = spdlog::rotating_logger_mt("Net", "Logs/Net.log", 1048576 * 5, 3);
        NetLog->set_pattern("[%Y-%m-%d %H:%M:%S.%e][%l] %v");
    }

    void Info(const std::string& message, LogType type)
    {
        switch (type)
        {
        case LogType::GAME:
            GameLog->info(message);
            break;
        case LogType::TERRAIN:
            TerrainLog->info(message);
            break;
        case LogType::PLAYER:
            PlayerLog->info(message);
            break;
        case LogType::NET:
            NetLog->info(message);
            break;
        }
    }

    void Warn(const std::string& message, LogType type)
    {
        switch (type)
        {
        case LogType::GAME:
            GameLog->warn(message);
            break;
        case LogType::TERRAIN:
            TerrainLog->warn(message);
            break;
        case LogType::PLAYER:
            PlayerLog->warn(message);
            break;
        case LogType::NET:
            NetLog->warn(message);
            break;
        }
    }

    void Error(const std::string& message, LogType type)
    {
        switch (type)
        {
        case LogType::GAME:
            GameLog->error(message);
            break;
        case LogType::TERRAIN:
            TerrainLog->error(message);
            break;
        case LogType::PLAYER:
            PlayerLog->error(message);
            break;
        case LogType::NET:
            NetLog->error(message);
            break;
        }
    }

    void Debug(const std::string &message, LogType type)
    {
        switch (type)
        {
        case LogType::GAME:
            GameLog->debug(message);
            break;
        case LogType::TERRAIN:
            TerrainLog->debug(message);
            break;
        case LogType::PLAYER:
            PlayerLog->debug(message);
            break;
        case LogType::NET:
            NetLog->debug(message);
            break;
        }
    }

    void Dispose()
    {
        GameLog->flush();
        GameLog = nullptr;
        
        PlayerLog->flush();
        PlayerLog = nullptr;

        TerrainLog->flush();
        TerrainLog = nullptr;

        NetLog->flush();
        NetLog = nullptr;
        
        ConsoleLog = nullptr;
    }
}
